package main

import (
	"context"
	"fmt"
	"gitee.com/Diegoh/go-study/go-color/text"
	"go.etcd.io/etcd/clientv3"
	"time"
)

func main() {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"localhost:2379", "localhost:22379", "localhost:32379"},
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		// handle error!
	}
	defer cli.Close()
	fmt.Println("etcd connected success")
	key := "/test/sample_key"

	//监听某个key单变化
	go watchKey(key, cli)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	resp, err := cli.Put(ctx, key, "sample_value")
	fmt.Printf("%v\n", resp)
	cancel()
	if err != nil {
		fmt.Printf("put to etcd failed, err:%v\n", err)
		return
	}

	//从etcd取key的值
	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	resp1, err1 := cli.Get(ctx, key)
	cancel()
	if err1 != nil {
		fmt.Printf("get from etcd failed, err:%v\n", err)
		return
	}
	for _, ev := range resp1.Kvs {
		fmt.Printf("read from etcd:%s:%s\n", ev.Key, ev.Value)
	}

	// 删除etcd中的某个key
	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	resp2, err2 := cli.Delete(ctx, key)
	if err2 != nil {
		fmt.Printf("delete from etcd failed, err:%v\n", err)
		return
	}
	fmt.Println(text.Red("delete response etcd:"), resp2)
	cancel()

	//租约  设置一个有过期时间的key
	// 创建一个5秒的租约
	leaseResp, errL := cli.Grant(context.TODO(), 5)
	if errL != nil {
		fmt.Printf("租约创建失败%v", errL)
	}

	// 5秒钟之后, /nazha/ 这个key就会被移除
	_, err = cli.Put(context.TODO(), "/lease/test", "dsb", clientv3.WithLease(leaseResp.ID))
	if err != nil {
		fmt.Printf("put失败%v", err)
	}
	// the key 'foo' will be kept forever
	ch, kaerr := cli.KeepAlive(context.TODO(), leaseResp.ID)
	if kaerr != nil {
		fmt.Printf("%v", kaerr)
	}
	for {
		ka := <-ch
		fmt.Println("ttl:", ka.TTL)
	}
}

/**
监听并打印key
*/
func watchKey(key string, cli *clientv3.Client) {
	fmt.Println(" start watching", key)
	rch := cli.Watch(context.Background(), key)
	for wresp := range rch {
		for _, ev := range wresp.Events {
			fmt.Printf("Key Changeed,Type: %s \n Key:%s Value:%s\n", ev.Type, ev.Kv.Key, ev.Kv.Value)
		}
	}
}
